package ae.pcfc.cldos.online.common.facade.provider;

import java.util.ArrayList;
import java.util.List;

import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.cldos.online.common.UltimusConstants;
import ae.pcfc.cldos.online.common.clddb.domain.AppMetaData;
import ae.pcfc.cldos.online.common.clddb.domain.ApplicationStatus;
import ae.pcfc.cldos.online.common.clddb.domain.ServiceMaster;
import ae.pcfc.cldos.online.common.clddb.domain.manager.AppMetaDataDOM;
import ae.pcfc.cldos.online.common.clddb.domain.manager.FnpGSDOM;
import ae.pcfc.cldos.online.common.etksdb.domain.User;
import ae.pcfc.cldos.online.common.etksdb.domain.manager.UserDomainObjectManager;
import ae.pcfc.cldos.online.common.exception.BadAppException;
import ae.pcfc.cldos.online.common.exception.FNPAppException;
import ae.pcfc.cldos.online.common.exception.PaymentException;
import ae.pcfc.cldos.online.common.facade.BaseFacade;
import ae.pcfc.cldos.online.common.facade.EntryPermitPaymentFacade;
import ae.pcfc.cldos.online.common.manager.FNPManager;
import ae.pcfc.cldos.online.common.manager.GsInfoManager;
import ae.pcfc.cldos.online.common.manager.TaskAndNotificationsManager;
import ae.pcfc.cldos.online.common.tscdb.domain.manager.TTscClientCompanyDOM;
import ae.pcfc.cldos.online.common.vo.UserVO;
import ae.pcfc.cldos.online.common.vo.ep.peyment.EntryPermitPaymentInfoVO;
import ae.pcfc.cldos.online.common.vo.ep.peyment.PaymentAdviceRequestVO;
import ae.pcfc.cldos.online.common.vo.fnp.FNPPaymentAdviceVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPAccountTypeVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPCatalogVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPFinalPaymentResponseVO;
import ae.pcfc.cldos.online.gs.ConstantsGS;
import ae.pcfc.cldos.online.gs.service.client.vo.NotificationVO;
import ae.pcfc.cldos.online.net.service.vo.AttachmentVO;
import ae.pcfc.cldos.online.wf.ConstantsWF;
import ae.pcfc.cldos.online.wf.service.client.GenericVisaWF;
import ae.pcfc.cldos.online.wf.service.client.vo.base.BaseGVariablesVO;
import ae.pcfc.cldos.online.wf.service.client.vo.base.CompleteStepVO;

/**
 * 
 * @author arosa
 *
 */
public class EntryPermitPaymentFacadeImpl extends BaseFacade implements EntryPermitPaymentFacade {

	private AppMetaDataDOM appMetaDataDOM;
	private GsInfoManager gsInfoManager;
	
	public GsInfoManager getGsInfoManager() {
		return gsInfoManager;
	}

	public void setGsInfoManager(GsInfoManager gsInfoManager) {
		this.gsInfoManager = gsInfoManager;
	}

	public void setAppMetaDataDOM(AppMetaDataDOM appMetaDataDOM) {
		this.appMetaDataDOM = appMetaDataDOM;
	}
	
	private TaskAndNotificationsManager taskAndNotificationsManager;
	
	public void setTaskAndNotificationsManager(
			TaskAndNotificationsManager taskAndNotificationsManager) {
		this.taskAndNotificationsManager = taskAndNotificationsManager;
	}
	
	private FNPManager fnpManager;
	
	public void setFnpManager(FNPManager fnpManager) {
		this.fnpManager = fnpManager;
	}
	
	private FnpGSDOM fnpGSDOM;
	
	public void setFnpGSDOM(FnpGSDOM fnpGSDOM) {
		this.fnpGSDOM = fnpGSDOM;
	}
	
	private UserDomainObjectManager userDomainObjectManager;
	
	public void setUserDomainObjectManager(
			UserDomainObjectManager userDomainObjectManager) {
		this.userDomainObjectManager = userDomainObjectManager;
	}
	
	private GenericVisaWF genericVisaWF;
	
	public void setGenericVisaWF(GenericVisaWF genericVisaWF) {
		this.genericVisaWF = genericVisaWF;
	}
	
	private TTscClientCompanyDOM tTscClientCompanyDOM;
	
	public void settTscClientCompanyDOM(
			TTscClientCompanyDOM tTscClientCompanyDOM) {
		this.tTscClientCompanyDOM = tTscClientCompanyDOM;
	}
	
	@Transactional
	public EntryPermitPaymentInfoVO getEntryPermitPaymentInfoByAppId(UserVO userVO, String appId) throws BadAppException,FNPAppException{
		EntryPermitPaymentInfoVO entryPermitPaymentInfoVO = new EntryPermitPaymentInfoVO();
		User user = userDomainObjectManager.findUserAndClientByUserName(userVO.getUsername());
		
		AppMetaData appMetaData = appMetaDataDOM.getAppMetaDataById(appId);
		
		if(appMetaData==null || !appMetaData.getClientId().equals(user.getClientId())){
			throw new BadAppException("BAD APP ID");
		}
		
		entryPermitPaymentInfoVO.setAppId(appMetaData.getApplicationId().toString());
		
		String serviceCode = null;
		Long statusCode = appMetaData.getApplicationStatus().getStatusCode();
		if(statusCode.equals(ApplicationStatus.PAYMENT_RENEWAL)){
			serviceCode = ServiceMaster.EP_RENEWAL;
		} else if (statusCode.equals(ApplicationStatus.PAYMENT_CANCELATION)){
			serviceCode = ServiceMaster.EP_CANCELATION;
		} else {
			throw new BadAppException("BAD TASK SATATUS CODE ASSIGNED TO APP STATUS");
		}
		
		List<String> fnpCodes = fnpGSDOM.getFnpCodeListByServiceCode(new Long(serviceCode));
		List<FNPCatalogVO> catalogVOs = fnpManager.retreiveFNPCatalog(fnpCodes);
		entryPermitPaymentInfoVO.setCatalogVOs(catalogVOs);
		
		entryPermitPaymentInfoVO.setClietnReferenceNumber(appMetaData.getClientRefNo());
		entryPermitPaymentInfoVO.setEmployeeName(appMetaData.getEmployeeDetail().getEdPsprtName());
		
		try{
			FNPAccountTypeVO fnpAccountTypeVO = fnpManager.enquireDeposits(user.getClient().getCTrakheesId());
			
			entryPermitPaymentInfoVO.setPrepaidAccBalance(fnpAccountTypeVO.getPrepaidAccBalance());
			entryPermitPaymentInfoVO.setReservedAccBalance(fnpAccountTypeVO.getReservedAccBalance());
			entryPermitPaymentInfoVO.setServiceName(appMetaData.getServiceMaster().getServiceName());
			entryPermitPaymentInfoVO.setTaskName(appMetaData.getApplicationStatus().getStatusDesc());
		}catch(Exception e){
			e.printStackTrace();
		}
		
		return entryPermitPaymentInfoVO;
	}
	
	
	
	@Transactional(rollbackFor=Exception.class)
	public boolean completePayment(
			PaymentAdviceRequestVO paymentAdviceRequestVO) throws Exception{
		String appId = paymentAdviceRequestVO.getAppId();
		UserVO userVO = paymentAdviceRequestVO.getUserVO();
		AppMetaData appMetaData = appMetaDataDOM.getPlainAppMetaDataById(appId);
		User user = userDomainObjectManager.findUserAndClientByUserName(userVO.getUsername());
		if(!userVO.isAdmin() || !appMetaData.getClientId().equals(user.getClientId())){
			throw new BadAppException("sdg");
		}
		
		String coLicNo = tTscClientCompanyDOM.getLicenseNumberNyTrakheesId(user.getClient().getCTrakheesId());
		
		BaseGVariablesVO baseGVariablesVO = new BaseGVariablesVO();
		baseGVariablesVO.setG_ApplicationID(appMetaData.getClientRefNo());
		
		CompleteStepVO completeStepVO = new CompleteStepVO();
		completeStepVO.setStrUserName(ConstantsWF.ULTIMUS_ANONYMOUS_USER);
		completeStepVO.setnIncidentNumber(new Integer(appMetaData.getWfIncidentId()));
		
		
		if(appMetaData.getStatusCode().equals(ApplicationStatus.PAYMENT_RENEWAL)){
			appMetaData.setStatusCode(ApplicationStatus.PAYMENT_RENEWAL_COMPLETED);
			completeStepVO.setStrStepName(UltimusConstants.EP_ONLINE_RENEWAL_PAYMENT);
		} else if(appMetaData.getStatusCode().equals(ApplicationStatus.PAYMENT_CANCELATION)){
			appMetaData.setStatusCode(ApplicationStatus.PAYMENT_CANCELATION_COMPLETED);
			completeStepVO.setStrStepName(UltimusConstants.EP_ONLINE_CANCELATION_PAYMENT);
			try{
				gsInfoManager.cancelGSAppRequest(appMetaData.getClientRefNo());
			}catch(Exception e){
				e.printStackTrace();
				throw new Exception(e);
			}
		}
		
		//appMetaData.setStatusCode(ApplicationStatus.STATUS_APPROVED_BY_GENERAL_ADMIN);
		//appMetaData.setWfStatus(AppMetaData.WF_STATUS_EP_PAYMENT);
		
		String fnpServiceId = paymentAdviceRequestVO.getFnpServiceCode();
		
		 FNPPaymentAdviceVO fnpPaymentAdviceVO = 
				fnpManager.generatePayment(appMetaData.getApplicationId(), userVO.getUsername(), fnpServiceId, paymentAdviceRequestVO.getFnpParams(),null,appMetaData.getClientRefNo());
		
		
		try{
			FNPFinalPaymentResponseVO fnpFinalPaymentResponseVO = 
					fnpManager.finalizePayment(appId, userVO.getUsername(), 
							fnpPaymentAdviceVO.getPaymentAdviceNumber());
			
			List<AttachmentVO> attachments = new ArrayList<AttachmentVO>(1);
			attachments.add(fnpFinalPaymentResponseVO.getAttachmentVO());
			
			/*Send notification*/
			NotificationVO notificationVO = new NotificationVO();
			notificationVO.setCoLicNo(coLicNo);
			notificationVO.setAttachments(attachments);
			notificationVO.setOnlineAppId(appMetaData.getApplicationId().toString());
			taskAndNotificationsManager.sendNotification(appMetaData, notificationVO);
		} catch (Exception e) {
			e.printStackTrace();
			throw new PaymentException(e);
		}
		
		/*We will set real flow statuses*/
		if(appMetaData.getStatusCode().equals(ApplicationStatus.PAYMENT_RENEWAL_COMPLETED)){
			appMetaData.setStatusCode(ApplicationStatus.STATUS_APPROVED_BY_GENERAL_ADMIN);
		} else if(appMetaData.getStatusCode().equals(ApplicationStatus.PAYMENT_CANCELATION_COMPLETED)){
			appMetaData.setStatusCode(ApplicationStatus.STATUS_CANCELED_BY_GENERAL_ADMIN);
		}
		appMetaDataDOM.update(appMetaData);
		taskAndNotificationsManager.completeAllByAppId(appMetaData.getApplicationId());
		
		try{
			genericVisaWF.completeStep(appMetaData.getProcessCode(), completeStepVO, baseGVariablesVO);
		} catch(Exception e){
			fnpManager.cancelPayment(appId, userVO.getUsername(), fnpPaymentAdviceVO.getPaymentAdviceNumber(),appMetaData.getClientRefNo());
			e.printStackTrace();
			throw new Exception(e);
		}
		
		return true;
		
	}
}
